/*
 ============================================================================
 Name        : main.c
 Author      : Jessay
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include <linux/input.h>
#include <string.h>
#include <errno.h>

#include "tangoc.h"
#include "keyboard.h"
#include "register.h"
#include "interrupt.h"
#include "power.h"
#include "debug.h"
#include "raster.h"
#include "reset.h"
#include "t_main.h"

#define  CALI_TIME   3
int gdev;

int select_calibrate(char cmd)
{
	int ret = 1;
	if (cmd == 'A' || cmd == 'a')
	{
		ret = 2;
	}
	return ret;
}

int input_calibrate_menu()
{
	char cmd = 'p';
	puts("[P] PIXCIR Calibrate.");
	puts("[A] AUO Calibrate.");
	printf("Input cmd: ");
	while (1)
	{
		cmd = getchar();
		if (cmd == 'a' || cmd == 'A' || cmd == 'p' || cmd == 'P')
		{
			break;
		}
	}
	while (getchar() != '\n');
	return select_calibrate(cmd);
}

int calibration()
{
	int i, arg = 0, ret;
	char buf[2];

	buf[0] = 0x3A;
	buf[1] = 0x03;
	ioctl(gdev, DISABLE_IRQ, 0);
	ioctl(gdev, CALIBRATION_FLAG, arg);
	printf("please wait..");
	fflush(stdout);
	ret = write(gdev, buf, 2);
	for (i = 0; i < CALI_TIME; i++)
	{
		msleep(1000);
		printf("..");
		fflush(stdout);
	}
	printf("\n");

	if (ret == 2)
	{
		printf("Calibrate successfully\n");
	}
	else
	{
		printf("Calibrate faild\n");
	}
	ioctl(gdev, RESET_TP, 0);
	msleep(100);
	ioctl(gdev, ENABLE_IRQ, 0);

	return ret == 2 ? 0 : -1;
}

int normal_mode(void)
{
	int i, ret, arg = 0;
	int x[5], y[5], id[5], touch;
	char wbuf[8];
	wbuf[0] = 0;
	init_keyboard();

	ioctl(gdev, NORMAL_MODE, arg);
	while (1)
	{
		char buf[32] = "\0";
		if (kbhit())
		{
			char key = getkey();
			if (key == '\n') break;
		}
		write(gdev, wbuf, 1);
		msleep(5);

		ret = read(gdev, buf, 32);
		touch = buf[0];
		if(touch>0 && touch<6)
		{
			printf("touch=%d\n", touch);
			for(i=0; i<touch; i++)
			{
				x[i] = ((buf[i*5+3] << 8) | (buf[i*5+2]));
				y[i] = ((buf[i*5+5] << 8) | (buf[i*5+4]));
				id[i] = (buf[i*5+6]);
				printf("x[%d]=%d y[%d]=%d id[%d]=%d\n", i, x[i], i, y[i], i, id[i]);
			}
		}
		msleep(5);
	}

	close_keyboard();
	return ret;
}

void main_menu()
{
	puts("\n[User mode] main menu, Press a key in brackes.");
	puts("[B] Bootloader mode.");
	puts("[C] Calibrate mode.");
	puts("[N] Normal mode");
	puts("[D] Debug mode.");
	puts("[R] Raster mode.");
	puts("[L] Lift mode.");
	puts("[I] INT mode");
	puts("[E] EEPROM mode.");
	puts("[T] Reset TP.");
	puts("[A] About me");
	puts("[X] Exit.");
}

int button_raw()
{
	int i, ret;
	unsigned char buf[8];
	ioctl(gdev, BUTTON_RAW, 0);
	ret = read(gdev, buf, 8);
	printf("Button raw data: ");
	for (i = 0; i < 8; i++)
	{
		printf("%c", buf[i]);
	}
	printf("\n");

	return ret;
}

int execute(void)
{
	int ret=0, num, type = 1, loop =1;
	char cmd, flag = 'n';
	char fname[64] = "/auto.pix";

	main_menu();
	while (loop)
	{
		printf("Input cmd: ");
		cmd = getchar();
		while (getchar() != '\n');
		switch (cmd)
		{
		case 't':
		case 'T':
			reset();
			break;
		case 'c':
		case 'C':
			ret = calibration();
			break;
		case 'n':
		case 'N':
			normal_mode();
			break;
		case 'r':
		case 'R':
			raster_mode();
			break;
		case 'l':
		case 'L':
			t_raster_mode();
			break;
		case 'd':
		case 'D':
			debug_mode();
			break;
		case 'b':
		case 'B':
			input_bootloader(fname, &flag);
			ret = bootloader_mode(fname, flag);
			break;
		case 'e':
		case 'E':
			EEPROM_mode();
			break;
		case 'i':
		case 'I':
			INT_mode();
			break;
		case 'a':
		case 'A':
			show_about();
			break;
		case 'x':
		case 'X':
			loop = 0;
			break;
		}
		main_menu();
	}
	return ret;
}

int perform(char *argv[])
{
	int ret=0, num = 0;
	char cmd = argv[1][1];
	switch (cmd)
	{
	case 'c':
	case 'C':
		ret = calibration();
		break;
	case 'b':
	case 'B':
		ret = bootloader_mode(argv[2], argv[3][0]);
		break;
	case 'a':
	case 'A':
		show_about();
		break;
	}
	return ret;
}

int open_device()
{
	int i;
	char fname[32];
	for (i = 0; i < 256; i++)
	{
		sprintf(fname, "/dev/pixcir_i2c_ts%d", i);
		gdev = open(fname, O_RDWR, S_IRUSR | S_IWUSR);
		if (gdev != -1) break;
	}
	if (gdev == -1)
	{
		puts("open device failed.");
		return -1;
	}
	return 0;
}

int is_user_mode()
{
	int ver = firmware_version();
	if(ver==TM70 || ver==TM80 || ver==TM81 || ver==TM82) return 0;
	return 1;
}

int load(int argc, char* argv[])
{
	int ret = 0;
	//if (is_user_mode())
	{
		ret = argc == 1 ? execute() : perform(argv);
	}
//	else
//	{
//		ret = t_execute();
//	}
	return ret;
}

int set_timeout(int64_t delay)
{
//    LOGI("set_last_user_activity_timeout delay=%d\n", ((int)(delay)));

	const char* const AUTO_OFF_TIMEOUT_DEV = "/sys/android_power/auto_off_timeout";
    int fd = open(AUTO_OFF_TIMEOUT_DEV, O_RDWR);
    if (fd >= 0)
    {
        char buf[32];
        ssize_t len;
        len = snprintf(buf, sizeof(buf), "%d", ((int)(delay)));
        buf[sizeof(buf) - 1] = '\0';
        len = write(fd, buf, len);
        close(fd);
        printf("set_timeout ok\n");
        return 0;
    }
    else
    {
    	 printf("set_timeout fail\n");
        return errno;
    }
}

int get_timeout()
{
//    LOGI("set_last_user_activity_timeout delay=%d\n", ((int)(delay)));

	const char* const AUTO_OFF_TIMEOUT_DEV = "/sys/android_power/auto_off_timeout";
    int fd = open(AUTO_OFF_TIMEOUT_DEV, O_RDONLY|O_CREAT);
    if (fd >= 0)
    {
        char buf[32];
        ssize_t len = 32;
       // len = snprintf(buf, sizeof(buf), "%d", ((int)(delay)));
      //  buf[sizeof(buf) - 1] = '\0';
        len = read(fd, buf, len);
        close(fd);
        printf("get_timeout ok\n");
        return 0;
    }
    else
    {
    	 printf("get_timeout fail\n");
        return errno;
    }
}

int main(int argc, char* argv[])
{
	int ret;
	int time = 0;

//	int i=0;
//	printf("show argv\n");
//	for(i=0; i<argc; i++)
//	{
//		printf("%s ", argv[i]);
//	}
//	printf("\n");

	puts("Begin.");

	//time = get_timeout();
	//set_timeout(10*60*1000);

	if ((ret=open_device())==0)
	{
		load(argc, argv);
		close(gdev);
	}

	puts("End.");
	return ret;
}

